home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 5 / Apprentice-Release5.iso / Source Code / C / Applications / Python 1.3.3 / Python 133 SRC / Mac / Demo / textedit / ped.py
Text File  |  1996-04-19  |  8KB  |  340 lines

  1. # A minimal text editor.
  2. #
  3. # To be done:
  4. # - Update viewrect after resize
  5. # - Handle horizontal scrollbar correctly
  6. # - Functionality: find, etc.
  7.  
  8. from Menu import DrawMenuBar
  9. from FrameWork import *
  10. import Win
  11. import Qd
  12. import TE
  13. import Scrap
  14. import os
  15. import macfs
  16.  
  17. class TEWindow(ScrolledWindow):
  18.     def open(self, path, name, data):
  19.         self.path = path
  20.         self.name = name
  21.         r = windowbounds(400, 400)
  22.         w = Win.NewWindow(r, name, 1, 0, -1, 1, 0x55555555)
  23.         self.wid = w
  24.         vr = 0, 0, r[2]-r[0]-15, r[3]-r[1]-15
  25.         dr = (0, 0, vr[2], 0)
  26.         Qd.SetPort(w)
  27.         Qd.TextFont(4)
  28.         Qd.TextSize(9)
  29.         self.ted = TE.TENew(dr, vr)
  30.         self.ted.TEAutoView(1)
  31.         self.ted.TESetText(data)
  32.         w.DrawGrowIcon()
  33.         self.scrollbars()
  34.         self.changed = 0
  35.         self.do_postopen()
  36.         self.do_activate(1, None)
  37.         
  38.     def do_idle(self):
  39.         self.ted.TEIdle()
  40.         
  41.     def getscrollbarvalues(self):
  42.         dr = self.ted.destRect
  43.         vr = self.ted.viewRect
  44.         height = self.ted.nLines * self.ted.lineHeight
  45.         vx = self.scalebarvalue(dr[0], dr[2]-dr[0], vr[0], vr[2])
  46.         vy = self.scalebarvalue(dr[1], dr[1]+height, vr[1], vr[3])
  47.         print dr, vr, height, vx, vy
  48.         return None, vy
  49.         
  50.     def scrollbar_callback(self, which, what, value):
  51.         if which == 'y':
  52.             if what == 'set':
  53.                 height = self.ted.nLines * self.ted.lineHeight
  54.                 cur = self.getscrollbarvalues()[1]
  55.                 delta = (cur-value)*height/32767
  56.             if what == '-':
  57.                 delta = self.ted.lineHeight
  58.             elif what == '--':
  59.                 delta = (self.ted.viewRect[3]-self.ted.lineHeight)
  60.                 if delta <= 0:
  61.                     delta = self.ted.lineHeight
  62.             elif what == '+':
  63.                 delta = -self.ted.lineHeight
  64.             elif what == '++':
  65.                 delta = -(self.ted.viewRect[3]-self.ted.lineHeight)
  66.                 if delta >= 0:
  67.                     delta = -self.ted.lineHeight
  68.             self.ted.TEPinScroll(0, delta)
  69.             print 'SCROLL Y', delta
  70.         else:
  71.             pass # No horizontal scrolling
  72.         
  73.     def do_activate(self, onoff, evt):
  74.         print "ACTIVATE", onoff
  75.         ScrolledWindow.do_activate(self, onoff, evt)
  76.         if onoff:
  77.             self.ted.TEActivate()
  78.             self.parent.active = self
  79.             self.parent.updatemenubar()
  80.         else:
  81.             self.ted.TEDeactivate()
  82.  
  83.     def do_update(self, wid, event):
  84.         Qd.EraseRect(wid.GetWindowPort().portRect)
  85.         self.ted.TEUpdate(wid.GetWindowPort().portRect)
  86.         self.updatescrollbars()
  87.         
  88.     def do_contentclick(self, local, modifiers, evt):
  89.         shifted = (modifiers & 0x200)
  90.         self.ted.TEClick(local, shifted)
  91.         self.updatescrollbars()
  92.         self.parent.updatemenubar()
  93.  
  94.     def do_char(self, ch, event):
  95.         self.ted.TESelView()
  96.         self.ted.TEKey(ord(ch))
  97.         self.changed = 1
  98.         self.updatescrollbars()
  99.         self.parent.updatemenubar()
  100.         
  101.     def close(self):
  102.         if self.changed:
  103.             save = EasyDialogs.AskYesNoCancel('Save window "%s" before closing?'%self.name, 1)
  104.             if save > 0:
  105.                 self.menu_save()
  106.             elif save < 0:
  107.                 return
  108.         if self.parent.active == self:
  109.             self.parent.active = None
  110.         self.parent.updatemenubar()
  111.         del self.ted
  112.         self.do_postclose()
  113.         
  114.     def menu_save(self):
  115.         if not self.path:
  116.             self.menu_save_as()
  117.             return # Will call us recursively
  118.         print 'Saving to ', self.path
  119.         dhandle = self.ted.TEGetText()
  120.         data = dhandle.data
  121.         fp = open(self.path, 'wb')  # NOTE: wb, because data has CR for end-of-line
  122.         fp.write(data)
  123.         if data[-1] <> '\r': fp.write('\r')
  124.         fp.close()
  125.         self.changed = 0
  126.         
  127.     def menu_save_as(self):
  128.         fss, ok = macfs.StandardPutFile('Save as:')
  129.         if not ok: return
  130.         self.path = fss.as_pathname()
  131.         self.name = os.path.split(self.path)[-1]
  132.         self.wid.SetWTitle(self.name)
  133.         self.menu_save()
  134.         
  135.     def menu_cut(self):
  136.         self.ted.TESelView()
  137.         self.ted.TECut()
  138.         Scrap.ZeroScrap()
  139.         TE.TEToScrap()
  140.         self.updatescrollbars()
  141.         self.parent.updatemenubar()
  142.         self.changed = 1
  143.         
  144.     def menu_copy(self):
  145.         self.ted.TECopy()
  146.         Scrap.ZeroScrap()
  147.         TE.TEToScrap()
  148.         self.updatescrollbars()
  149.         self.parent.updatemenubar()
  150.         
  151.     def menu_paste(self):
  152.         print 'SCRAP', Scrap.InfoScrap(), `Scrap.InfoScrap()[1].data`
  153.         TE.TEFromScrap()
  154.         self.ted.TESelView()
  155.         self.ted.TEPaste()
  156.         self.updatescrollbars()
  157.         self.parent.updatemenubar()
  158.         self.changed = 1
  159.         
  160.     def menu_clear(self):
  161.         self.ted.TESelView()
  162.         self.ted.TEDelete()
  163.         self.updatescrollbars()
  164.         self.parent.updatemenubar()
  165.         self.changed = 1
  166.         
  167.     def have_selection(self):
  168.         return (self.ted.selStart < self.ted.selEnd)
  169.  
  170. class Ped(Application):
  171.     def __init__(self):
  172.         Application.__init__(self)
  173.         self.num = 0
  174.         self.active = None
  175.         self.updatemenubar()
  176.         
  177.     def makeusermenus(self):
  178.         self.filemenu = m = Menu(self.menubar, "File")
  179.         self.newitem = MenuItem(m, "New window", "N", self.open)
  180.         self.openitem = MenuItem(m, "Open...", "O", self.openfile)
  181.         self.closeitem = MenuItem(m, "Close", "W", self.closewin)
  182.         m.addseparator()
  183.         self.saveitem = MenuItem(m, "Save", "S", self.save)
  184.         self.saveasitem = MenuItem(m, "Save as...", "", self.saveas)
  185.         m.addseparator()
  186.         self.quititem = MenuItem(m, "Quit", "Q", self.quit)
  187.         
  188.         self.editmenu = m = Menu(self.menubar, "Edit")
  189.         self.undoitem = MenuItem(m, "Undo", "Z", self.undo)
  190.         self.cutitem = MenuItem(m, "Cut", "X", self.cut)
  191.         self.copyitem = MenuItem(m, "Copy", "C", self.copy)
  192.         self.pasteitem = MenuItem(m, "Paste", "V", self.paste)
  193.         self.clearitem = MenuItem(m, "Clear", "", self.clear)
  194.         
  195.         # Not yet implemented:
  196.         self.undoitem.enable(0)
  197.         
  198.         # Groups of items enabled together:
  199.         self.windowgroup = [self.closeitem, self.saveitem, self.saveasitem, self.editmenu]
  200.         self.focusgroup = [self.cutitem, self.copyitem, self.clearitem]
  201.         self.windowgroup_on = -1
  202.         self.focusgroup_on = -1
  203.         self.pastegroup_on = -1
  204.         
  205.     def updatemenubar(self):
  206.         changed = 0
  207.         on = (self.active <> None)
  208.         if on <> self.windowgroup_on:
  209.             for m in self.windowgroup:
  210.                 m.enable(on)
  211.             self.windowgroup_on = on
  212.             changed = 1
  213.         if on:
  214.             # only if we have an edit menu
  215.             on = self.active.have_selection()
  216.             if on <> self.focusgroup_on:
  217.                 for m in self.focusgroup:
  218.                     m.enable(on)
  219.                 self.focusgroup_on = on
  220.                 changed = 1
  221.             on = (Scrap.InfoScrap()[0] <> 0)
  222.             if on <> self.pastegroup_on:
  223.                 self.pasteitem.enable(on)
  224.                 self.pastegroup_on = on
  225.                 changed = 1
  226.         if changed:
  227.             DrawMenuBar()
  228.  
  229.     #
  230.     # Apple menu
  231.     #
  232.     
  233.     def do_about(self, id, item, window, event):
  234.         EasyDialogs.Message("A simple single-font text editor")
  235.             
  236.     #
  237.     # File menu
  238.     #
  239.  
  240.     def open(self, *args):
  241.         self._open(0)
  242.         
  243.     def openfile(self, *args):
  244.         self._open(1)
  245.  
  246.     def _open(self, askfile):
  247.         if askfile:
  248.             fss, ok = macfs.StandardGetFile('TEXT')
  249.             if not ok:
  250.                 return
  251.             path = fss.as_pathname()
  252.             name = os.path.split(path)[-1]
  253.             try:
  254.                 fp = open(path, 'rb') # NOTE binary, we need cr as end-of-line
  255.                 data = fp.read()
  256.                 fp.close()
  257.             except IOError, arg:
  258.                 EasyDialogs.Message("IOERROR: "+`arg`)
  259.                 return
  260.         else:
  261.             path = None
  262.             name = "Untitled %d"%self.num
  263.             data = ''
  264.         w = TEWindow(self)
  265.         w.open(path, name, data)
  266.         self.num = self.num + 1
  267.         
  268.     def closewin(self, *args):
  269.         if self.active:
  270.             self.active.close()
  271.         else:
  272.             EasyDialogs.Message("No active window?")
  273.         
  274.     def save(self, *args):
  275.         if self.active:
  276.             self.active.menu_save()
  277.         else:
  278.             EasyDialogs.Message("No active window?")
  279.         
  280.     def saveas(self, *args):
  281.         if self.active:
  282.             self.active.menu_save_as()
  283.         else:
  284.             EasyDialogs.Message("No active window?")
  285.             
  286.         
  287.     def quit(self, *args):
  288.         for w in self._windows.values():
  289.             w.close()
  290.         if self._windows:
  291.             return
  292.         raise self
  293.         
  294.     #
  295.     # Edit menu
  296.     #
  297.     
  298.     def undo(self, *args):
  299.         pass
  300.         
  301.     def cut(self, *args):
  302.         if self.active:
  303.             self.active.menu_cut()
  304.         else:
  305.             EasyDialogs.Message("No active window?")
  306.         
  307.     def copy(self, *args):
  308.         if self.active:
  309.             self.active.menu_copy()
  310.         else:
  311.             EasyDialogs.Message("No active window?")
  312.         
  313.     def paste(self, *args):
  314.         if self.active:
  315.             self.active.menu_paste()
  316.         else:
  317.             EasyDialogs.Message("No active window?")
  318.  
  319.     def clear(self, *args):
  320.         if self.active:
  321.             self.active.menu_clear()
  322.         else:
  323.             EasyDialogs.Message("No active window?")
  324.         
  325.     #
  326.     # Other stuff
  327.     #    
  328.  
  329.     def idle(self, *args):
  330.         if self.active:
  331.             self.active.do_idle()
  332.  
  333. def main():
  334.     App = Ped()
  335.     App.mainloop()
  336.     
  337. if __name__ == '__main__':
  338.     main()
  339.     
  340.